/*
you can get more refer from https://gitee.com/yiliangwu880/svr_util.git
事件驱动架构，发布-订阅模式或者观察者模式
使用写法简洁。事件参数强类型


相互于 publish_subscribe.h 有区别。
核心优势：
1. 局部事件管理：避免全局事件带来的无效回调检查
2. 自动注销：对象销毁时自动清理相关事件监听
3. 类型安全：事件参数强类型，编译期检查
4. 解耦设计：适用于复杂对象内部组件间的通信

典型应用场景：
- 游戏角色与技能、Buff等子系统的交互
- 组件化架构中的模块间通信
- 需要精确控制生命周期的回调场景

例子：
#include "game_util/event_mgr.h"
	namespace su //必须要定义名空间
	{
		template<>
		struct EventMgrTrait<1> {
			using Fun = void(int i);
		};
		template<>
		struct EventMgrTrait<2> {
			using Fun = void(int a, int b);
		};
		template<>
		struct EventMgrTrait<3> {
			using Fun = void(int a, int b);
		};
	}
	class Player;

	//组件的方式复用 （推荐用，减少类继承层次，代码好维护）
	struct Sub3
	{
		EventReg m_EventReg;
		Sub3(Player &owner)
		:m_EventReg(owner.mgr)
		{
			m_EventReg.Reg<0>([this](){ //m_EventReg释放时，自动注销事件，所以这里捕获this安全
				//to do event
			});
			m_EventReg.Reg<1>(*this, &Sub3::OnEvent0);
		}
		void OnEvent0()
		{
		}
		void Release()
		{
			m_EventReg.Unreg(0);//释放指定event0关联侦听， 如果注册多个lambda到event0,会注销多个
		}
	};

	//继承的方式复用 （不推荐，考虑废除）
	struct Sub1 : public EventCom
	{
		Player &m_owner;
		Sub1(Player &owner)
		:EventCom(owner.mgr)
		{
			Reg<1>(&Sub1::OnE0); //this释放，会自动注销注册
		}

		void OnE1(int i)
		{
		}
	};
	struct Sub2 : public EventCom
	{
		....
		Sub2()
		{
			Reg<0>(&Sub2::OnE1);
		}
		void OnE0()
		{
		}
	};

	class Player :  public B1
	{
	public:
		EventMgr mgr;
		Sub1 m_Sub1;
		Sub2 m_Sub2;
	};

	{
		Player m;

		m.mgr.FireEvent<0>();
		m.mgr.FireEvent<1>(5);

	}

*/
#pragma once

#include <vector>
#include <unordered_map>
#include <functional>
#include <memory>
#include <any>
#include <set>
#include "typedef.h"
#include <functional>
#include <tuple>
#include "static_reg.h"
#include "misc.h"
#include "log_def.h" //不同项目，需要改。 日志宏


//定义事件ID 关联 接收函数参数列表

namespace su
{

	//推导lambda特征用
	template <class Fn>
	struct LambdaTrait;
	template <class T, class Ret, class ... Args>
	struct LambdaTrait<Ret(T::*)(Args...) const> //提示输入单个参数时的推导格式
	{
		using Tuple = std::tuple<std::decay_t<Args>...>;
		using Fun = std::function<void(Args...)>;
		using BaseFun = void(Args...);
	};

	template<int ID>
	struct EventMgrTrait {
		using Fun = void();
	};
	static const size_t MAX_EVENT_ID = 64;
	class EventMgr: public su::EnableWeakPtr<EventMgr>
	{
		friend class EventCom;
		friend class EventReg;
	

		//委托
		struct Delegate
		{
			void *ins = nullptr;//对象指针
			std::any memFun; //成员函数指针 ，例如 void (Player::*)();
			std::any funObj; //函数对象 function<xx> 类型
		};
		//委托集合
		struct Delegates
		{
			bool m_bFiring = false;
			std::vector<Delegate> vec;
		};

		std::array<Delegates, MAX_EVENT_ID> m_id2obss; //eventId idx Observers
		std::vector<std::any*> vecWillDoFunObj;//将要回调中的代理
	public:
		~EventMgr()
		{
			for (auto& v : m_id2obss)
			{
				if (v.m_bFiring) {
					L_FATAL("destory EventMgr when FireEvent");//致命错误，对象函数还在调用中，就销毁自己了
				}
			}
		}
		//one reg create one observer
		size_t GetObserverNum(uint32 ID)
		{
			if (ID>= m_id2obss.size())
			{
				LERROR("id overload", ID);
				return 0;
			}
			return m_id2obss[ID].vec.size();
		}
		template<int ID, class ... Args>
		void FireEvent(Args&& ... args)
		{
			if (ID >= m_id2obss.size())
			{
				LERROR("id overload", ID);
				return;
			}
			Delegates &ss = m_id2obss[ID];
			if (ss.m_bFiring) //触发回调过程中，禁止递归调用 触发相同ID，销毁EventMgr 避免复杂调用流程。
			{
				L_ERROR("can't recursion FireEvent");
				return;
			}
			using FunObj = std::function<typename EventMgrTrait<ID>::Fun>;
			for (Delegate &v : ss.vec)
			{
				vecWillDoFunObj.push_back(&v.funObj);
			}

			ss.m_bFiring = true;
			while (!vecWillDoFunObj.empty())
			{
				FunObj* pFun = std::any_cast<FunObj>(vecWillDoFunObj.back());
				vecWillDoFunObj.pop_back();
				//最后调用，回调中改变 ss.vec 状态也不影响。
				//回调函数里面可以 注册，注销操作， 注册不回触发这次fire不回调，注销马上生效，取消本次fire将要的回调
				(*pFun)(std::forward<Args>(args)...);
			}
			ss.m_bFiring = false;
		}

	private:
		//注意：需要用户保证事件回调时， ins不野。
		template<int ID, class ReturnType, class... Args, class T>
		void Reg(ReturnType(T::* fun)(Args...), T &ins)
		{
			{
				using IDFun = typename EventMgrTrait<ID>::Fun;
				using RegFun = ReturnType (Args...);
				static_assert(std::is_same<IDFun, RegFun>::value);
			}

			if (ID >= m_id2obss.size())
			{
				LERROR("id overload", ID);
				return;
			}
			if (fun == nullptr)
			{
				L_ERROR("can't RegEvent with nullptr");
				return;
			}
			using MemFun = ReturnType (T::*) (Args...);

			Delegates& ss = m_id2obss[ID];
			std::vector<Delegate>& vec = ss.vec;
			for (const Delegate& v : vec)
			{
				const MemFun* pFun = std::any_cast<const MemFun>(&(v.memFun));
				if (v.ins == &ins && *pFun == fun)
				{
					L_ERROR("repeated reg");
					return;
				}
			}
			std::function<ReturnType(Args...)> f = [&ins, fun](Args... args)->ReturnType
			{
				(ins.*fun)(args...);
			};
			vec.emplace_back(Delegate{ &ins, fun, f });
		}
		
		//Reg支持 注册lambda, 函数对象 std::function<...>
		//注意多次注册就回多次触发lambda. 注销只能用 UnregByIns的方法
		//注意：需要用户保证事件回调时， ins不野。
		template<int ID, class Lambda, class T>
		void Reg(Lambda cb, T& ins)
		{
			using LambdaT = LambdaTrait<decltype(&decltype(cb)::operator())>;
			typename LambdaT::Fun fun(cb);
			{
				using IDFun = typename EventMgrTrait<ID>::Fun;
				using RegFun = typename LambdaT::BaseFun;
				static_assert(std::is_same<IDFun, RegFun>::value);
			}

			if (ID >= m_id2obss.size())
			{
				LERROR("id overload", ID);
				return;
			}
			if (fun == nullptr)
			{
				L_ERROR("can't RegEvent with nullptr");
				return;
			}
			Delegates& ss = m_id2obss[ID];

			ss.vec.emplace_back(Delegate{ &ins, 0, fun });
		}

		inline void DelWillCb(std::any *funObj)
		{
			for (size_t i = 0; i < vecWillDoFunObj.size(); ++i)
			{
				if (vecWillDoFunObj[i] == funObj)
				{
					vecWillDoFunObj[i] = vecWillDoFunObj[vecWillDoFunObj.size() - 1];
					vecWillDoFunObj.erase(vecWillDoFunObj.end() - 1);
				}
			}
		}
		template<int ID, class T, class ReturnType, class... Args>
		bool Unreg(ReturnType(T::* fun)(Args...), T *ins)
		{
			{
				using IDFun = typename EventMgrTrait<ID>::Fun;
				using RegFun = ReturnType(Args...);
				static_assert(std::is_same<IDFun, RegFun>::value);
			}

			using MemFun = ReturnType(T::*)(Args...);
			if (ID >= m_id2obss.size())
			{
				LERROR("id overload", ID);
				return false;
			}
			Delegates &ss = m_id2obss[ID];
			std::vector<Delegate> &vec = ss.vec;
			for (Delegate &v : vec)
			{
				if (v.ins == ins)//先用对象快速筛选
				{
					MemFun *pFun = std::any_cast<MemFun>(&v.memFun);
					if (nullptr != pFun && *pFun == fun)
					{
						DelWillCb(&v.funObj);
						v = vec.back();
						vec.erase(vec.end() - 1);
						return true;
					}
				}
			}
			return false;
		}
		
		void Unreg(void *ins)
		{
			int32 id = -1;
			for (auto &ss: m_id2obss)
			{
				id++;
				std::vector<Delegate> &vec = ss.vec;
				std::vector<size_t> vecDelIdx;
				size_t idx = 0;
				for (Delegate &v : vec)
				{
					if (ins == v.ins)
					{
						vecDelIdx.push_back(idx);
					}
					idx++;
				}
				for (auto it = vecDelIdx.rbegin(); it != vecDelIdx.rend(); ++it)//have bug when del more
				{
					size_t i = *it;
					for (Delegate& v : vec)
					{
						DelWillCb(&v.funObj);
					}
					vec[i] = vec.back();
					vec.erase(vec.end() - 1);
				}
			}
		}

		void Unreg(void* ins, int ID)
		{
			if (ID>=(int)m_id2obss.size() || ID<0)
			{
				LERROR("error para");
				return;
			}
			auto& ss = m_id2obss[ID];
			std::vector<Delegate>& vec = ss.vec;
			std::vector<size_t> vecDelIdx;
			size_t idx = 0;
			for (Delegate& v : vec)
			{
				if (ins == v.ins)
				{
					vecDelIdx.push_back(idx);
				}
				idx++;
			}
			for (auto it = vecDelIdx.rbegin(); it != vecDelIdx.rend(); ++it)//have bug when del more
			{
				size_t i = *it;
				for (Delegate& v : vec)
				{
					DelWillCb(&v.funObj);
				}
				vec[i] = vec.back();
				vec.erase(vec.end() - 1);
			}
		}
	};

	template<class DerivedType, class BaseType>
	struct TIsDerivedFrom
	{
		// Different size types so we can compare their sizes later.
		typedef char No[1];
		typedef char Yes[2];

		// Overloading Test() s.t. only calling it with something that is
		// a BaseType (or inherited from the BaseType) will return a Yes.
		static Yes& Test(BaseType*);
		static Yes& Test(const BaseType*);
		static No& Test(...);

		// Makes a DerivedType ptr.
		static DerivedType* DerivedTypePtr() { return nullptr; }

	public:
		// Test the derived type pointer. If it inherits from BaseType, the Test( BaseType* ) 
		// will be chosen. If it does not, Test( ... ) will be chosen.
		static const bool Value = sizeof(Test(DerivedTypePtr())) == sizeof(Yes);

		static const bool IsDerived = Value;
	};



	//不推荐使用了。 推荐用EventReg
	//继承后，能让对象注册成员函数为事件函数
	class EventCom
	{
		su::WeakPtr<EventMgr> m_mgr;
	public:
		EventCom(EventMgr &mgr)
			:m_mgr(mgr)
		{
		}

		//如果T有虚函数, EventCom没有，  (void*)this > (void*)(T *)this 8个字节
		//必须要有虚函数，避免子类对象 地址 和 this不一样
		virtual ~EventCom() 
		{
			if (EventMgr* pMgr = m_mgr.Get())
			{
				pMgr->Unreg(this);
			}
		}

		//fun 为T类成员函数。必须为this所属类型。 
		// 函数参数特征 和 ID不匹配，编译报错
		template<int ID, class T, class ReturnType, class... Args>
		void Reg(ReturnType(T::* fun)(Args...))
		{
			static_assert(TIsDerivedFrom<T, EventCom>::IsDerived);
			L_ASSERT(dynamic_cast<T*>(this) != nullptr);//避免传入别的类型函数，不是本对象类型。 会消耗效率
			if (EventMgr* pMgr = m_mgr.Get())
			{
				//如果T有虚函数, EventCom没有， this > (T *)this 8个字节 , 所以这里需要 ((T *)this) 才能正确
				pMgr->Reg<ID>(fun, *((T *)this)); 
			}
		}

		//Reg支持 注册lambda, 函数对象 std::function<...>
		//注意多次注册就回多次触发lambda. 注销只能用 UnregAll的方法
		// 函数参数特征 和 ID不匹配，编译报错
		template<int ID, class Lambda>
		void Reg(Lambda fun)
		{
			if (EventMgr* pMgr = m_mgr.Get())
			{
				pMgr->Reg<ID>(fun, *this); 
			}
		}

		// 函数参数特征 和 ID不匹配，编译报错
		template<int ID, class T, class ReturnType, class... Args>
		bool Unreg(ReturnType(T::* fun)(Args...))
		{
			static_assert(TIsDerivedFrom<T, EventCom>::IsDerived);
			if (EventMgr* pMgr = m_mgr.Get())
			{
				return pMgr->Unreg<ID>(fun, (T *)this);
			}
			return false;
		}

		//注销属于本对象的所有委托
		void UnregAll()
		{
			if (EventMgr* pMgr = m_mgr.Get())
			{
				pMgr->Unreg(this);
			}
		}
	};

	class EventReg
	{
		su::WeakPtr<EventMgr> m_mgr;
	public:
		EventReg(EventMgr& mgr)
			:m_mgr(mgr)
		{
		}

		~EventReg()
		{
			if (EventMgr* pMgr = m_mgr.Get())
			{
				pMgr->Unreg(this);
			}
		}

		//注意：ins 必须拥有 this， 才能保证ins回调的时候不野。
		template<int ID, class T, class ReturnType, class... Args>
		void Reg(T& ins, ReturnType(T::* fun)(Args...))
		{
			//ins错误检查，消耗效率
			void* insAddr = &ins;
			if (!((uint64)this >= (uint64)insAddr && (uint64)this <= (uint64)insAddr + sizeof(T)))
			{
				LERROR("ins is error. ins not own this. maybe ins will pending when eventfire");
				return;
			}
			auto f = [&ins, fun](Args... args)->ReturnType
			{
				(ins.*fun)(args...);
			};
			if (EventMgr* pMgr = m_mgr.Get())
			{
				pMgr->Reg<ID>(f, *this);
			}
		}

		//支持 注册lambda, 函数对象 std::function<...>
		//注意多次注册就回多次触发lambda. 注销只能用 UnregAll的方法
		template<int ID, class Lambda>
		void Reg(Lambda fun)
		{
			if (EventMgr* pMgr = m_mgr.Get())
			{
				pMgr->Reg<ID>(fun, *this);
			}
		}
		//注销属于本对象 注册的事件ID
		void Unreg(int ID)
		{
			if (EventMgr* pMgr = m_mgr.Get())
			{
				pMgr->Unreg(this, ID);
			}
		}
		//注销属于本对象 注册的所有委托
		void Unreg()
		{
			if (EventMgr* pMgr = m_mgr.Get())
			{
				pMgr->Unreg(this);
			}
		}
	};
}
